// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: wsfuyibing <682805@qq.com>
// Date: 2025-02-25

package consul

import (
	"fmt"
	"gitee.com/go-libs/console"
	"kv/providers"
	"regexp"
	"strings"
)

// Entity
// 在 Consul 中每个 Key 实体.
type Entity struct {
	// Key
	// 名称.
	Key Key `json:"key"`

	// Value
	// 值.
	Value []byte `json:"value"`

	// Text
	// 转码后的原始正文.
	Text string `json:"-"`
}

// Generate
// 生成目标.
func (o *Entity) Generate(abs string, key Key) (targets []*providers.Target) {
	targets = make([]*providers.Target, 0)

	if m := regexMatchFilename.FindStringSubmatch(
		fmt.Sprintf(`%s%s`,
			abs, strings.TrimPrefix(o.Key.String(), key.String()),
		),
	); len(m) > 0 {
		target := providers.NewTarget()
		target.Path = m[1]
		target.Name = m[2]
		target.Text = o.Text
		targets = append(targets, target)
	}
	return
}

// Parse
// 解析实体.
func (o *Entity) Parse(container *console.Container, host string) (err error) {
	var (
		k  Key
		ke error
		ks []*Entity
		m  []string
	)

	// 1. 正文转码。
	o.Text = fmt.Sprintf(`%s`, o.Value)

	// 2. 遍历变量.
	//    处理配置原始内容时, 若配置中使用的变量, 则通过变量将其值替换为真实数据.
	//    例如: 数据库连接地址、账号、密码等.
	for _, r := range []*regexp.Regexp{regexWithVariable, regexWithCompatibleVariable} {
		// 2.1 退出遍历.
		if err != nil {
			return
		}

		// 2.2 匹配变量.
		o.Text = r.ReplaceAllStringFunc(o.Text, func(s string) string {
			// 2.2.1 退出遍历.
			if err != nil {
				return s
			}

			// 2.2.2 复用原值.
			if m = r.FindStringSubmatch(s); len(m) != 2 {
				return s
			}

			// 2.2.3 忽略空值.
			//       若变量是空值, 则使用空字符串替代.
			if k = Key(m[1]); k.IsBlank() {
				return ""
			}

			// 2.2.4 取变量值.
			if ks, ke = k.Get(container, host); ke != nil {
				if err == nil {
					err = ke
				}
				return s
			}

			// 2.2.5 递归遍历.
			for _, v := range ks {
				// 忽略目录.
				if v.Key.IsDir() {
					continue
				}

				// 递归解析.
				if ke = v.Parse(container, host); ke != nil {
					if err == nil {
						err = ke
					}
					return s
				}
				return v.Text
			}
			return ""
		})
	}
	return
}
